home *** CD-ROM | disk | FTP | other *** search
- COMMENT $
-
- DOS32 Version 0.1
-
- A 32 bit MSDOS extender for assembly programmers
-
- supporting
-
- Dos Protected Mode Interrupt Specification
- and
- System BIOS extended memory copy service (INT 15h AH = 87h)
- for without DPMI.
-
-
-
- Written by Adam Seychell SEP-1993
-
- email s921880@minyos.xx.rmit.oz.au
-
-
-
- $
-
- .386p ; Enable "REAL" CPU instuctions.
-
- Normal_stack equ 200h ; Size of your protected mode stack
- V86_stack_size equ 200h ; Size of stack for V86 interrupt calls
-
- PIC_Base equ 80h ; Base interrupt address for the 8259s
-
-
- Data_sruct struc
- C_EDI dd 0
- C_ESI dd 0
- C_EBP dd 0
- C_resrved dd 0
- C_EBX dd 0
- C_EDX dd 0
- C_ECX dd 0
- C_EAX dd 0
- C_FLAGS dw 0
- C_ES dw 0
- C_DS dw 0
- C_FS dw 0
- C_GS dw 0
- C_IP dw 0
- C_CS dw 0
- C_SP dw 0
- C_SS dw 0
- ends
-
-
- RealData struc
- Real_GS dd 0
- Real_FS dd 0
- Real_DS dd 0
- Real_ES dd 0
- Real_SS dd 0
- Real_ESP dd 0
- tmp_Real_intNum db 0
- ends
-
- DATA32 SEGMENT PUBLIC 'DATA' USE32
-
- global CODE32_sel :word
- global CODE16_sel :word
- global DATA_sel :word
- global TheSTACK_sel :word
- global VIDEO_sel :word
- global FLAT_DATA_sel :word
- global FLAT_CODE32_sel :word
- global XMS_sel :word
- global BASE_sel :word
- global PSP_sel :word
- global xms_usage :dword
- global xms_base :dword
- global Base_Segment :word
- global PSP_segment :word
- ENDS
-
-
- global START32 :near
- global IRQ0 :near
- global IRQ1 :near
- global IRQ2 :near
- global IRQ3 :near
- global IRQ4 :near
- global IRQ5 :near
- global IRQ6 :near
- global IRQ7 :near
- global IRQ8 :near
- global IRQ9 :near
- global IRQ10 :near
- global IRQ11 :near
- global IRQ12 :near
- global IRQ13 :near
- global IRQ14 :near
- global IRQ15 :near
-
- DATA32 SEGMENT PUBLIC 'DATA' USE32
-
- DOS_CODE_sel dw DOS_CODE_Desc - GDT
- DOS_DATA_sel dw DOS_DATA_Desc - GDT
-
- tss_Level0ESP dd 0
- V86_Lv0_StkSave dd 10h dup (0) ; TSS level 0 ESP save for V86 calls.
- IDT_base dd 0
- _tmp0_ dd 0
- _tmp1_ dd 0
- tmp_Real_Flags dd 0
- V86_irq_Count db 0
-
- DATA32 ENDS
-
-
-
- CODE16 SEGMENT PUBLIC 'CODE' USE16
- CODE16 ends
-
- DATA16 SEGMENT PUBLIC 'DATA' USE16
- DATA16 ends
-
- CODE32 SEGMENT PUBLIC 'CODE' USE32
- assume DS:DATA32 , CS:CODE32 , es:DATA32
-
-
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
- Setup_Pmode: ; first 32bit protected mode point
-
-
- sti
- db 0eah ; jump to start of main program
- dd offset start32 , code32_desc - gdt
-
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
- ;************** EXCEPTION HANDLERS ... *********************
- Exception:
- mov ax,DATA_Desc - GDT
- mov ds,ax
- mov es,Flat_data_sel
- mov ss,TheStack_sel
- mov fs,FLAT_data_sel
- mov gs,FLAT_data_sel
- mov esp,100h
- mov dx,offset unknown_int_exit_mesg
- mov ebp,'ERRA' ; Exit with error code
- int 21h
-
- getexeec macro n
- _386exception_&n&:
- mov dx,offset e_&n
- jmp All_exceptions
- endm
- x=0
- rept 16
- getexeec %x
- x=x+1
- endm
-
- ;ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ
- All_exceptions:
- mov esp,100h
- ; jmp _Pmode_exit_error
-
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
- _Pmode_exit_error:
- mov ax,TheSTACK_Desc - GDT
- mov ss,ax
- mov ebp,'ERRA'
- int 21h ; Exit with error
-
-
- set1STirqm macro nt
- firstIRQ&nt:
- push offset irq&nt
- jmp check_HardwareINT
- endm
-
- x = 0
- rept 16
- set1STirqm %x
- x=x+1
- endm
-
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
- ;ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ
- check_HardwareINT proc near
- test dword ptr [esp+3*4],020000h
- jz not_v86_irq ; jump if IRQ was from P.mode
-
- push eax ; IRQ was from V86 mode.
- mov eax,[esp+5*4] ; Put new V86 stack pointer
- mov SS:[real_ESP],eax
- mov eax,[esp+6*4] ; Put new V86 stack segment
- mov SS:[real_SS],eax ; we Don't care about ES,DS,FS & GS
- pop eax
-
- mov fs,[esp+10*4] ; return segment reg selectors
- mov ds,[esp+11*4] ; as they were before entering V86
- mov gs,[esp+12*4]
- mov es,[esp+13*4]
- not_v86_irq:
- ret ; Go to IRQ handler
- endp
-
-
-
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
- ;ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ
- ;------- The General Exception Handler ---------------
- ;ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ
- General_Exeption_Handler:
-
- test dword ptr [esp+4*3],0020000h ; Test VM bit
- jnz V86_Monitor
- mov dx,offset e_13
- jmp All_Exceptions
-
-
-
- ;*****************************************
- ;********* Virtual 8086 exception handler *********
- ;*****************************************
- V86_Monitor proc
- add esp,4 ; delete the undocumented pushed error code
- pushad
- mov ax,Flat_DATA_Desc - GDT
- mov fs,ax
-
- ;;; Find what instruction caused the exception ;;;;
- movzx ebx,word ptr [esp+36] ; Get CS from stack
- shl ebx,4
- add ebx,[esp+32] ; Get EIP form stack
- inc dword ptr [esp+32]
- mov dl,fs:[ebx] ; Get opcode
- mov al,3
- cmp dl,0cch ; see if INT 3 Breakpoint
- je short DO_v86int ; if so do it's int
- mov al,4
- cmp dl,0ceh ; See if INTO
- je short Do_v86int ; if so do it's int
- cmp dl,0cdh ; see if INT n
- jne V86exc ; if not then exception
- inc dword ptr [esp+32] ; It must be a INT n instruction
- mov al,fs:[ebx+1] ; get INT n number
-
- cmp al,0FFh ; If int 0ffh and Then
- jz Exit_V86 ; return to main Program
-
- cmp al,15h
- jnz NoXmsToCopy
-
- cmp byte ptr ss:[esp+7*4+1],87h ; Detect if v86 application
- jz Emulate_XMS_COPY ; wants to copy extended mem
- ; i.e ah = 87h
-
- NoXmsToCopy:
-
- ;****; Emulate V86 interrupt ;****;
- DO_v86int: ; Do interrupt "AL" for V86 task
- movzx ebx,al
- shl ebx,2 ; Get 8086 Int Vector
- movzx edx,word ptr [esp+(8+4)*4] ; Get SS stored on stack
- shl edx,4
- sub word ptr [esp+(8+3)*4],6 ; Sub ESP stored on stack by 6
- add edx,[esp+(8+3)*4] ; edx = Phyical Address of V86 stack
- mov ax,[esp+(8+2)*4] ;Put FLAGS from Prev.0 Stack to V86 stack
- mov fs:[edx+4],ax
- mov ax,[esp+(8+1)*4] ;Put CS from Prev.0 Stack to V86 stack
- mov fs:[edx+2],ax
- mov ax,[esp+(8+0)*4] ;Put IP from Prev.0 Stack to V86 stack
- mov fs:[edx],ax
- mov eax,fs:[ebx] ; Get real mode int vector (CS:IP)
- mov [esp+(8+0)*4],ax ; Store it on prev. 0 Stack
- shr eax,16
- mov [esp+(8+1)*4],ax
- ret86: and word ptr [esp+(8+2)*4],0fcffh
- popad ; Clear DF & IF flags on prev. 0 Stack
- iretd ; Return to V86 mode
-
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
- Exit_V86:
- mov ax,DATA_Desc - GDT
- mov ds,ax
- popad
- mov [_tmp0_],eax
- mov [_tmp1_],ebx
-
- add esp,8 ; ignore EIP & CS
- pop word ptr [esp+12*4+2] ; Get V86 EFLAGS onto
- add esp,2 ; stack from the int 20h
- pop ss:[Real_ESP]
- pop ss:[Real_SS]
- pop ss:[Real_ES]
- pop ss:[Real_DS]
- pop ss:[Real_FS]
- pop ss:[Real_GS]
-
-
- ;Must return the TSS Level 0 ESP to the previous V86 call's Level 0 ESP value.
- movzx eax,V86_irq_Count
- sub al,1
- jle jH98_V86 ; Only do it if a V86 call inside a call.
- dec V86_irq_Count
- dec eax
- mov eax,[V86_Lv0_StkSave+EAX*4] ; Get previous TSS Lv0 ESP
- mov ebx,[tss_Level0ESP] ; Get address of TSS Lv0 ESP
- mov fs:[ebx],eax ; Load it.
- jH98_V86:
-
- mov eax,[_tmp0_] ;Return temperaly saved registers
- mov ebx,[_tmp1_]
-
- pop fs ds ; pop seg reg from the entering V86
- pop gs es ; call; see My_EmulateRealInterupt proc
-
- iretd ; Return to main program
-
-
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
- ;ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ
- ; Emulate the SYSTEM BIOS - COPY EXTENDED MEMORY Srevice for V86 application
- ; INT 15 & AH = 87h
- ;ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ
-
- COMMENT $
-
- NOTE.
- There is a problem with the BIOS int 15h ah = 87 emulation
- when HIMEM.SYS calls it to transfer a XMS block while MSDOS is loaded
- in the Upper Memeory Block. It seems to be called with the location
- of the GDT ( for int 15 ah=87 ) in the ROM area. This gives an invalid GDT.
- When DOS is loaded into convention memory everything work fine because
- HIMEM.SYS returns a valid GDT on this call.
- $
-
- Emulate_XMS_COPY: ; A20 gate always seems to be on ?
- ; mov ax,DATA_Desc - GDT
- ; mov ds,ax
-
- mov ecx,ss:[esp+(6)*4] ; Get Number of words to copy
- and ecx,0ffffh
- cmp cx,8000h
- ja _error_1587
- shr ecx,1
-
- xor eax,eax
- mov ax,ss:[esp+(8+5)*4] ; Get ES
- shl eax,4
- add ax,ss:[esp+(1)*4] ; Get SI
- adc eax,0 ; EAX has location of GDT
- mov ebx,eax
- ; sub ebx,0f0000h
- ; cmp ebx,010000h
- ; ja _error_1587
- ; push eax
- mov esi,fs:[eax+7h+10h]
- shl esi,24
- mov edx,fs:[eax+2h+10h] ; Get 32bit Source address
- and edx,0ffffffh
- add esi,edx
-
- mov edi,fs:[eax+7h+18h]
- shl edi,24
- mov edx,fs:[eax+2h+18h] ; Get 32bit Destination address
- and edx,0ffffffh
- add edi,edx
-
-
- ; write 'Source ',12
- ; mov edx,esi
- ; call hex_dword
-
- ; write ' Destination ',12
- ; mov edx,edi
- ; call hex_dword
-
- ; write ' Cout ',12
- ; mov edx,ecx
- ; shl edx,2
- ; call hex_dword
-
- ; write ' GDT ',12
- ; pop edx
- ; call hex_dword
-
- ; write ' CS:EIP ',10
- ; movzx edx,word ptr [esp+36] ; Get CS from stack
- ; shl edx,4
- ; add edx,[esp+32] ; Get EIP form stack
- ; call hex_dword
- ;
- ; write 'int 15 vect',11
- ; movzx edx,word ptr fs:[15h*4+2]
- ; shl edx,4
- ; add dx,fs:[15h*4]
- ; adc edx,0
- ; call hex_dword
- ; writeln
-
- push fs
- pop es
- cld
- rep movs dword ptr es:[edi],es:[esi] ; do the transfer
-
- mov byte ptr [esp+(7*4)+1],00 ;return AH = 0
-
- and byte ptr [esp+(8+2)*4],NOT 01 ; Clear Carry flag on prev. 0 Stack
-
- jmp ret86
-
- _error_1587:
- or byte ptr [esp+(8+2)*4],01 ; Set Carry flag on prev. 0 Stack
- mov byte ptr [esp+(7*4)+1],03 ;return AH
- jmp ret86
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
-
-
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
- ;ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ
- V86exc:
- mov dx,offset _V86_illigal_err
- jmp _Pmode_exit_error
-
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
-
- ;≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠
-
-
- endp
-
-
-
- ;**********************************
- MyDPMI_services:;*********************
- ;**********************************
- cmp ax,0205h
- jz SetPmodeintVector
- cmp ax,0204h
- jz GetPmodeintVector
- cmp ax,0400h
- jz GetVersion
- iretd
-
- SetPmodeintVector:
- push edi ebx fs ds
- mov ax,data_desc - gdt
- mov ds,ax
- mov fs,[flat_DATA_sel]
- movzx ebx,bl
- mov edi,ebx
- sub edi,Pic_Base ; No allowed to set the hardware int vectors
- cmp edi,15
- jbe Set_irq_vec
- mov edi,[idt_base]
- mov fs:[ebx*8+edi],dx ; offset 0..15
- SHR EDX,16
- mov fs:[ebx*8+edi+6],dx ; offset 16..32
- mov fs:[ebx*8+edi+2],cx ; Code Selector
- pop ds fs ebx edi
- iretd
-
- GetPmodeintVector:
- push edi ebx fs ds
- mov ax,data_desc - gdt
- mov ds,ax
- mov fs,[flat_DATA_sel]
- movzx ebx,bl
- shl ebx,3
- add ebx,[idt_base]
- mov edi,[idt_base]
- mov dx,fs:[ebx+6] ; Get offset 16..32
- SHL EDX,16
- mov dx,fs:[ebx] ; Get offset 0..15
- mov cx,fs:[ebx+2] ; Get Code Selector
- ivec22: pop ds fs ebx edi
- iretd
-
- Set_irq_vec:
- stc
- jmp ivec22
-
-
- GetVersion: ; Emulate DPMI service Get Version
- ; only need to emulate the returned values of PIC bases
- mov dh,PIC_base
- mov dl,PIC_base+8
- iretd
-
- ;ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ
- ; PROCEDURE TO EMULATE REAL MODE INTERRUPT
- ;
- ;ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ
- DPMI_EmulateRealInterupt proc far
- push ax
- push 0 0 0
- push word ptr ss:[Real_DS]
- push word ptr ss:[Real_ES]
- push word ptr [esp+18+8]
- pushad
- mov edi,esp
- push es
- push ss
- pop es
- mov ax,0300h
- mov bl,ss:[tmp_Real_intNum]
- xor ecx,ecx
- int 31h ; Use the DPMI service
- pop es
- popad
- pop word ptr [esp+26] ; return eflags
- pop word ptr ss:[Real_ES]
- pop word ptr ss:[Real_DS]
- add esp,14
- iretd
- ENDP
-
-
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
- My_EmulateRealInterupt proc far
-
- push es gs ds fs ; save segment registers.
- push eax
-
- mov ax,data_desc - gdt ; Load seg regs.
- mov ds,ax
- mov fs,[flat_data_sel]
-
- pop _tmp0_ ; temperly save eax.
-
- mov eax,[esp+4*6] ; Get flags from stack.
- mov [tmp_Real_Flags],eax ; Temperaly saved them.
-
- mov eax,[tss_Level0esp] ; Set Level 0 stack to current ESP
- mov fs:[eax],esp
-
- movzx eax,V86_irq_Count
- mov [V86_Lv0_StkSave+EAX*4], ESP
- inc V86_irq_Count
-
- pushfd ; Clear Nested Task, ( bit 14 )
- pop eax ; If set then the 386 will
- and ah,10111111b ; use the back link field in the TSS
- push eax ; to switch tasks. A no no.
- popfd
-
- mov eax,seg V86IntNumber
- shl eax,4
-
- push ebx ; Load the V86 interrupt number
- mov bl,SS:[tmp_Real_intNum] ; get it
- mov byte ptr fs:[offset V86IntNumber+1+EAX],BL ; put it
- pop ebx
- push SS:[Real_GS] ; GS
- push SS:[Real_FS] ; FS
- push SS:[Real_DS] ; DS
- push SS:[Real_ES] ; ES
- push SS:[Real_SS] ; SS
- push SS:[Real_ESP] ; ESP
- mov eax,00023000h ; IOPL = 3 , VM = 1
- or ax,word ptr [tmp_Real_Flags]
- push eax ; EFLAGS
- mov eax,seg TASK0_V86
- push eax ; CS
- mov eax,offset TASK0_V86
- push eax ; EIP
- mov eax,_tmp0_ ; Return origonal EAX value
- IRETD ; Enter V86 mode !!!!!
- endp
- ;≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠≠
-
- TASK0_V86:
-
- V86IntNumber: int 000h
- int 0ffh ; exit V86 mode
-
- CODE32 ENDS
-
-
-
-
-
-
-
-
-
- DOS_CODE SEGMENT PUBLIC 'CODE' USE16
- assume CS:dos_CODE , DS:DOS_CODE , fs:data32
-
- ;
- ; Format of a 386DX TSS (Task State Segment)
- ;
- tss struc
- tss_prev dw 0 ,0 ; back link to previous TSS
- tss_esp0 dd 0 ; Priv. 0 ESP
- tss_ss0 dw 0 ; Priv. 0 SS
- dw 0 ; unused
- tss_esp1 dd 0 ; Priv. 1 ESP
- tss_ss1 dw 0 ; Priv. 1 SS
- dw 0 ; unused
- tss_esp2 dd 0 ; Priv. 2 ESP
- tss_ss2 dw 0 ; Priv. 2 SS
- dw 0 ; unused
- tss_cr3 dd 0 ; PDBR
- tss_eip dd 0
- tss_eflags dd 0
- tss_eax dd 0
- tss_ecx dd 0
- tss_edx dd 0
- tss_ebx dd 0
- tss_esp dd 0
- tss_ebp dd 0
- tss_esi dd 0
- tss_edi dd 0
- tss_es dw 0,0
- tss_cs dw 0,0
- tss_ss dw 0,0
- tss_ds dw 0,0
- tss_fs dw 0,0
- tss_gs dw 0,0
- tss_ldt dw 0,0
- tss_t dw 0 ; if bit 0 set, exception on tsk switch
- tss_iobase dw 068h ; points to beg. of I/O permissions map
- tss_iomap db 2000h dup (0) ; I/O permissions bit map
- tss_ioend db 11111111b ; I/O map trailer
- TSS_ENDS equ $
- tss ends
-
-
- s_ACCESS record d_P:1,d_DPL:2,s_S:1,d_TYPE:4
- s_INFO record d_G:1,d_D:1,d_nul:1,d_avl:1,d_lim:4
-
- align 8
- GDT dd 0,0 ; First descriptor is always NULL.
-
- ; Data DESCRIPTOR for a FLAT memory model
- Flat_Data_Desc dw 0ffffh ; Limit[15..0]
- db 0,0,0 ; Base[23..0]
- s_ACCESS <1,00b,1,0010b> ; P,DPL,1,type[E=0,ED,W,A ]
- s_INFO <1,1,0,0,0fh> ; G,B,0,avl,Limit[19..16]
- db 0 ; Base[31..24]
-
- ; Code DESCRIPTOR for a FLAT memory model
- Flat_Code32_Desc dw 0ffffh ; Limit[15..0]
- db 0,0,0 ; Base[23..0]
- s_ACCESS <1,00,1,1010b> ; P,DPL,1,type[E=1,C,R,A ]
- s_INFO <1,1,0,0,0fh> ; G,D,0,avl,Limit[19..16]
- db 0 ; Base[31..24]
-
- ; Data DESCRIPTOR for the free extented memory block
- XMS_Desc dw 0000h ; Limit[15..0]
- db 00,00,10h ; Base[23..0]
- s_ACCESS <1,00b,1,0010b> ; P,DPL,1,type[E=0,ED,W,A ]
- s_INFO <1,0,0,0,00h> ; G,B,0,avl,Limit[19..16]
- db 0 ; Base[31..24]
-
- ; Data DESCRIPTOR with base = start of free base memory
- BASE_Desc dw 0ffffh ; Limit[15..0]
- db ?,?,? ; Base[23..0]
- s_ACCESS <1,00,1,0010b> ; P,DPL,1,type[E=0,ED,W,A ]
- s_INFO <0,0,0,0,0fh> ; G,B,0,avl,Limit[19..16]
- db 0 ; Base[31..24]
-
- ; Data DESCRIPTOR with base = 0A0000h
- Video_Desc dw 0ffffh ; Limit[15..0]
- db 00,00,0Ah ; Base[23..0]
- s_ACCESS <1,00,1,0010b> ; P,DPL,1,type[E=0,ED,W,A ]
- s_INFO <0,0,0,0,01h> ; G,B,0,avl,Limit[19..16]
- db 0 ; Base[31..24]
-
-
- ; Data DESCRIPTOR for the STACK
- TheSTACK_Desc dw Normal_stack-1 ; Limit[15..0]
- db 00,00,00h ; Base[23..0]
- s_ACCESS <1,00,1,0010b> ; P,DPL,1,type[E=0,ED,W,A ]
- s_INFO <0,1,0,0,00h> ; G,B,0,avl,Limit[19..16]
- db 0 ; Base[31..24]
-
- ; 16bit data and code DESCRIPTORS for real mode ( DOS )
- DOS_Code_Desc dw 0ffffh ; Limit[15..0]
- db ?,?,? ; Base[23..0]
- s_ACCESS <1,00,1,1010b> ; P,DPL,1,type[E=1,C,R,A ]
- s_INFO <0,0,0,0,00h> ; G,D,0,avl,Limit[19..16]
- db 0 ; Base[31..24]
-
- Dos_Data_Desc dw 0ffffh ; Limit[15..0]
- db ?,?,? ; Base[23..0]
- s_ACCESS <1,00,1,0010b> ; P,DPL,1,type[E=0,ED,W,A ]
- s_INFO <0,0,0,0,0h> ; G,B,0,avl,Limit[19..16]
- db 0 ; Base[31..24]
-
-
- ; Data PSP Descr with base = PSP , limit = 100h
- PSP_desc dw 0ffh ; Limit[15..0]
- db 00,00,00h ; Base[23..0]
- s_ACCESS <1,00,1,0010b> ; P,DPL,1,type[E=0,ED,W,A ]
- s_INFO <0,0,0,0,00h> ; G,B,0,avl,Limit[19..16]
- db 0 ; Base[31..24]
-
- ; DATA and CODE DESCRIPTORS for your dos extender
-
- Code32_Desc dw 0ffffh ; Limit[15..0]
- db ?,?,? ; Base[23..0]
- s_ACCESS <1,00,1,1010b> ; P,DPL,1,type[E=1,C,R,A ]
- s_INFO <0,1,0,0,0fh> ; G,D,0,avl,Limit[19..16]
- db 0 ; Base[31..24]
-
- Code16_Desc dw 0ffffh ; Limit[15..0]
- db ?,?,? ; Base[23..0]
- s_ACCESS <1,00,1,1010b> ; P,DPL,1,type[E=1,C,R,A ]
- s_INFO <0,0,0,0,0fh> ; G,D,0,avl,Limit[19..16]
- db 0 ; Base[31..24]
-
-
- Data_Desc dw 0ffffh ; Limit[15..0]
- db ?,?,? ; Base[23..0]
- s_ACCESS <1,00b,1,0010b> ; P,DPL,1,type[E=0,ED,W,A ]
- s_INFO <0,0,0,0,0fh> ; G,B,0,avl,Limit[19..16]
- db 0 ; Base[31..24]
-
-
- MyMain_TSS_Desc dw TSS_ends ; Limit[15..0]
- db ?,?,? ; Base[23..0]
- s_ACCESS <1,00,0,09h> ; P,DPL,0,(type = avalible 386 TSS )
- s_INFO <0,0,0,0,00h> ; G,0,0,0,Limit[19..16]
- db 0 ; Base[31..24]
-
-
- GDT_ends equ $ - GDT
-
-
- ;======== ERROR MESSAGES FOR PROGRAM TERMINATION IN NON-DPMI ===============
- unknown_int_exit_mesg db 'Exited from Unhandled protected mode interrupt',10,13,36
- _V86_illigal_err db 10,13,' Invalid Instuction in V86 mode ',10,13,36
- _exit_errror db 10,10,' PROGRAM TERMINATED ',10,13,7,36
- e_0 db '0 Divide error',10,13,36
- e_1 db '1 Debug exception',10,13,36
- e_2 db '2 Non-Maskable interrupt',10,13,36
- e_3 db '3 Breakpoint',10,13,36
- e_4 db '4 Overflow',10,13,36
- e_5 db '5 Range Exceeded',10,13,36
- e_6 db '6 Invalid opcode',10,13,36
- e_7 db '7 No math unit avalible',10,13,36
- e_8 db '8 Reserved',10,13,36
- e_9 db '9 Reserved',10,13,36
- e_10 db '10 Invalid TSS',10,13,36
- e_11 db '11 Segment Not Present',10,13,36
- e_12 db '12 Stack exception',10,13,36
- e_13 db '13 General Protection Exception',10,13,36
- e_14 db '14 Page fault',10,13,36
- e_15 db '14 Reserved',10,13,36
-
- DOS_IDT_value dw 03ffh,0,0,0
-
- DPMI_entry dw 0,0
- xms_usage_tmp dd 0
- _tmpL_xms_base dw 0
- _tmpH_xms_base dw 0
- xms_driver dd 0
- XMS_handle dw 0,0
- oirqMask db 0,0
- DPMI_Selector dw 0
- PIC1_Base db 0
- PIC2_Base db 0
-
- ;----------------------------------------------------------------------------
- ;ƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒ INTERNAL ROUTINES ƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒ
- ;----------------------------------------------------------------------------
-
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
- free_XMS_memory proc near
- cmp [xms_driver],0
- jz No_xms_driver
-
-
- ; UNLOCK THE ALLOCATED EXTENDED MEMORY BLOCK
- mov ah,0Dh
- mov dx,[XMS_handle]
- call [XMS_Driver]
-
- ; FREE ALLOCATED BLOCK
- MOV AH,0Ah
- mov dx,[XMS_handle]
- call [xms_driver]
- No_xms_driver: RET
-
- free_XMS_memory endp
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
- ;ƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒ
- ; Set new IRQ vector numbers
- set_8259intvec proc ; Set IRQ vectors 0..7 to bl
- ; and IRQ vectors 8..15 to bh
-
- CLI ;˘˙˘˙˘˙˘˙˘˙˘˙ set first 8259A PIC ˘˙˘˙˘˙˘˙˘˙˘˙
-
- mov al,00010001b ;ICW1
- out 20h,al ;icw4 is needed
- call Delay8259
- mov al,bl ;ICW2
- out 21h,al ;( Set PIC 1 Base interrupt number )
- call Delay8259
- mov al,4h ;ICW3
- out 21h,al
- call Delay8259
- mov al,1h ;ICW4
- out 21h,al
- call Delay8259 ;˘˙˘˙˘˙˘˙˘˙˘˙ set second 8259A PIC ˘˙˘˙˘˙˘˙˘˙˘˙
- mov al,00010001b ;ICW1
- out 0a0h,al ;icw4 is needed
- call Delay8259
- mov al,bh ;ICW2
- out 0a1h,al ;( Set PIC 2 Base interrupt number )
- call Delay8259
- mov al,00000010b ;ICW3
- out 0a1h,al
- call Delay8259
- mov al,0000001b ;ICW4
- out 0a1h,al
- call Delay8259
- ret
-
- delay8259: mov ax,1000h
- @3del: dec ax
- jnz @3del
- ret
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
- ;ƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒ
- endp
-
-
-
- Go_REAL_MODE proc near
-
- ;ƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒ
- ; Entry point to exit proteceded mode and restore hardware configeration.
- ; Then exits back to MSDOS. ( only for non-DPMI )
- ;ƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒ
- cli
-
- mov al,00110100b ; SLOW DOWN TIMER
- out 43h,al
- XOR AL,AL
- out 40h,al
- out 40h,al
-
- ; Exit protected mode and return to DOS
-
- ; Load Data registers with 8086 SEGMENTs
- mov ax,DOS_Data_Desc - GDT
- mov ss,ax
- mov es,ax
- mov ds,ax
- mov fs,ax
- mov gs,ax
-
-
- cli
- lidt qword ptr DOS_IDT_value ; Set IDT to how DOS want's it
-
- ; Exit protecded mode
- mov eax,CR0
- and al,NOT 1 ;Clear PE bit
- mov CR0,eax
-
- db 0eah
- dw To_MSDOS , Dos_CODE ; reload CS:IP
-
- To_MSDOS: ;-- remap IRQ int vectors ---
- mov bl,008h
- mov bh,070h
- call set_8259intvec
-
-
- assume ds:dos_code
- mov ax,dos_code
- mov ds,ax
- mov ax,TheStack ; Set up a bit of stack just to exit
- mov ss,ax
- mov esp,100h
-
- mov al,oirqMask ; return origonal values of the IRQ mask bits
- out 21h,al
- mov al,oirqMask+1
- out 0A1h,al
-
-
- mov al,20h
- out 20h,al
- out 0a0h,al
-
- in al,60h
-
- cmp ebp,'ERRA'
- jnz normal_terminate
- ; Print error message if need to
- mov ah,9
- int 21h
- mov dx,offset _exit_errror
- int 21h
-
- normal_terminate:
-
- call free_XMS_memory ; deallocated XMS
-
- Exit_To_MSDOS:
- mov ax,4C00h
- int 21h
- assume ds:dos_code
-
- endp
-
- ;---------------- finished exiting routine -------------------------
-
- COMMENT $
-
- All data below this point of this segment is not needed after initalization.
- Thus it can be (next Version) over witten after all the setting up is done.
- This saves a bytes. See the 32bit setup code at "Setup_Pmode:" above.
-
- >->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->
- $
-
- align 16
- NON_DPMI_initalize_start:
-
-
- GDTR_value dw GDT_ends - 1
- dd offset GDT
- IDTR_value dq 0000000007ffh
-
- Label InterruptGATE_a dword
- dw offset exception ; Offset[15..0]
- dw Code32_Desc - GDT ; Selector
- Label InterruptGATE_b dword
- db 00000000b ; 0,0,0,WordCnt[4..0]
- s_ACCESS <1,00b,0,0Eh> ; P,DPL,0,type = 386 interrupt Gate
- dw 0 ; Offset[31..16]
-
-
- ;ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ INITALIZATION ERROR MESSAGES ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ
- _inV86_err db ' Unable to enter protected mode because another protected mode ',10,13
- db 'application is operating and does not support Dos Protected Mode Interface',10,13
- db 'specifiaction.',10,13,10
- db ' Disable the protected mode sofware and try again.',10,13,36
- mesg_TimeOut8042 db 'Time out error in the keyboard controller (8042) failing to ',10,13,' respond on enabling the A20 gate.',10,13
- all_DPMI_err db 'Encountered DPMI error: ',36
- pmiERr db 'Switching to protecded mode.',10,13,36
- No_Mem_err db 'Not Enough Base memory. 6000 bytes needed.',10,13,36
- erralc_mesg db 'Can''t allocate descriptors.',10,13,36
- errset_mesg db 'Can''t Set descriptors.',10,13,36
- dpmi_aloc_err db 'Can''t allocate extended memory.',10,13,36
- dpmi_lock_err db 'Unable to lock allocated memory.',10,13,36
- dpmi_free_err db 'Unable to get free memory information.',10,13,36
- mesgA20_err db 'ERROR: Physical A20 gate test failed.',10,13,36
- xms_mesgA20_err db 'ERROR: XMS enabling the A20 gate.',10,13,36
- xms_vers_err db 'Need XMS v3.0 or greater.',10,13,36
- xms_alloc_Err db 'Can''t allocate XMS memory.',10,13,36
- xms_lock_err db 'Can''t lock allocated XMS memory.',10,13,36
-
- CALL_DATA Data_sruct <>
-
-
- DosStart proc
- mov ax,DATA32
- mov fs,ax
- mov fs:[psp_segment],DS ; store psp_segment
-
- mov ax,DOS_CODE
- mov ds,ax
-
- ; Get end of program address segment
- mov bx,SP
- shr bx,4
- inc bx
- mov ax,SS
- add bx,ax
- mov FS:Base_Segment,bx
-
-
-
- ; SET GLOBAL DISCRIPTOR TABLE Base Values ( USEING THE MACRO )
-
- Fix_Desc_BASE Macro Descriptor,RealSeg
- xor eax,eax
- mov ax,RealSeg
- shl eax,4
- mov word ptr [Descriptor +2 ],ax
- shr eax,16
- mov byte ptr [Descriptor+ 4 ],al
- ENDM
-
- Fix_Desc_BASE PSP_desc ,fs:[psp_segment]
-
- Fix_Desc_BASE CODE32_desc ,CODE32
-
- Fix_Desc_BASE CODE16_desc ,CODE16
-
- Fix_Desc_BASE DATA_desc ,DATA32
-
- Fix_Desc_BASE DOS_CODE_desc ,DOS_CODE
-
- Fix_Desc_BASE DOS_DATA_desc ,DOS_CODE
-
- Fix_Desc_BASE TheStack_desc , TheSTACK
-
-
-
- ;------------------------- A 2 0 G A T E -------------------------------
- ; ENABLE THE A20 GATE
- ; If a XMS Driver is installed then use the Driver to enable the A20
- ; If it's done directly (with 8042) ,the XMS Driver will not have
- ; track of the A20 state and usualy ends up hanging the system.
- ;
- ;-----------------------------------------------------------------------------
-
- ; Look for XMS driver installation
- mov ax,4300h
- int 2fh
- cmp al,80h
- jnz No_XMS
- ; ELSE A XMS Driver is installed
- push ES
- mov ax,4310h ; get Driver entry point
- int 2fh
- mov word ptr xms_Driver,bx
- mov word ptr xms_Driver+2,es
- POP ES
-
- ; LOCAL ENABLE A20 GATE
- mov ah,05h
- call xms_Driver
- cmp ax,1
- Jz A20_XMS_OK
- mov dx,offset xms_mesgA20_err
- jmp exit_InitError
- A20_XMS_OK:
-
- jmp A20_Controlled ; ready to go protecded mode
-
- ;-- Waiting procedures for enabling the A20 directly --
- Wait_until_status_bit0_is_1 proc
- st0_clear:
- xor cx,cx
- in al,64h
- test al,1
- jnz st0_set
- loop st0_clear
- jmp A20_8042_timeout
- st0_set: ret
- endp
-
- wait_until_status_bit1_is_0 proc
- st1set: xor cx,cx
- in al,64h
- test al,2
- jz st1_clear
- loop st1set
- jmp A20_8042_timeout
- st1_clear: ret
- endp
- ;----- jumps here if a time out error in enableing the A20 line ---
- A20_8042_timeout:
- mov dx,offset mesg_TimeOut8042
-
- exit_InitError: mov ah,9 ; Prints error mesage and terminates
- int 21h
- call free_XMS_memory
- mov ah,4ch
- int 21h
-
-
- No_XMS: ;------- Jumps here if no XMS driver is installed ---------------
-
-
- ;--- Must enable A20 directly through the 8042 ( keyboard controller)----
- ; It does this by setting bit 1 of the 8042's output port wich is
- ; inaccessable to the CPU Bus.
-
- cli
- call wait_until_status_bit1_is_0
- mov al,0adh ;send disable keyboard command
- out 64h,al ; viar 8042
-
- call wait_until_status_bit1_is_0
- mov al,0d0h ;Send read 8042 output port cmd
- out 64h,al
-
- call wait_until_status_bit0_is_1
- in al,60h ; read the output port and save it
- push ax
-
- call wait_until_status_bit1_is_0
- mov al,0d1h ; write output port cmd
- out 64h,al
-
- call wait_until_status_bit1_is_0
- pop ax ; write data to the output port
- or al,2
- ; and al,not 2
- out 60h,al ; seting bit 1 > enables A20
-
- call wait_until_status_bit1_is_0
- mov al,0aeh ;enable keyboard again
- out 64h,al
-
- call wait_until_status_bit1_is_0 ; wait a bit more
-
-
-
-
- ;----- check if A20 really is enabled -------------
- mov ax,0FFFFh
- mov es,ax
- mov ax,0
- mov gs,ax
- mov bl,gs:[0] ;Compare location 00000000 to 100000h
- cmp es:[10h],bl ; Check if the same
- jnz A20_enabled ; if not equal then A20 must be on.
-
- not byte ptr es:[10h] ; Cange byte at adreess 100000h.
- mov bl,es:[10h]
- mov al,gs:[00]
- not byte ptr es:[10h] ; Put back value
- cmp al,bl ; Now see if the same
- jnz A20_enabled
-
-
- ;--- EXIT on A20 error ----
- mov dx , offset mesgA20_err
- jmp exit_InitError ; print error mesg and exit
-
-
- ; --- A20 is deffently enabled ---
- A20_enabled:
-
-
- A20_Controlled: ; The A20 line should be enabled at this point
-
-
- ;-------------------------- A20 ACTIVE ------------------------------------
- ;-----------------------------------------------------------------------------
-
- ;ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ
- ;ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ SEE IF NEED TO USE DPMI OR NOT ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ
- ;ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ
-
- ; USE DPMI TO ENTER PROTECTED MODE
-
- ; Obtain the Real (V86) to Protected Mode Switch Entry Point
- mov ax,1687h
- int 2Fh
- and ax,ax
- jnz No_DPMI
- mov [DPMI_entry],di ; DPMI is installed
- mov [DPMI_entry+2],es
-
- mov fs:[Base_Segment],SS
-
- mov ax,theStack ; use Protected Mode stack area
- mov ss,ax
- mov sp,Normal_stack
-
-
- ; Use memory for the DPMI OS private data area
- mov es,fs:[Base_Segment]
- add fs:Base_Segment,si
- cmp fs:Base_Segment,09900h ; See if enough base memory
- jae no_mem
-
- call Allocate_Base ; Set descriptor base to here
-
- mov eax,fs:[xms_usage]
- mov xms_usage_tmp,eax
-
- mov gs,fs:[psp_segment] ;Save environment pointer
- push word ptr gs:[2Ch]
-
-
- ; Call the V86 To Protected Mode Switch Entry Point
- mov ax,1 ; use 32 DPMI ( big stack )
- call dword ptr [DPMI_entry]
- Jc Cant_Enter_dmpiPMode
-
-
- ;************** NOW IN DPMI PROTECTED MODE ******************
- ; as a 16 bit but want 32 bit
-
- push ds ; load ES to data segment
- pop es
-
- cmp xms_usage_tmp,0
- jz No_DPMI_MEMORY
-
- ; Get Free memory info
- mov ax,0500h
- mov edi,offset Call_data
- int 31h
- mov word ptr Call_data.c_edx,offset dpmi_free_err
- jc print_error
-
- mov eax,dword ptr Call_data+08h ; get lockable size (pages)
- shl eax,12 ; convert limit pages into Bytes
-
- ; Only Allocate memory defined in xms_usage
- cmp eax,xms_usage_tmp
- jbe LvDmpiSize
- mov eax,xms_usage_tmp
- LvDmpiSize: mov xms_usage_tmp,eax
-
-
- mov ebx,eax
- shr ebx,12
- dec ebx
- mov word ptr [XMS_desc+0],bx ; Set xms descriptor Limit
- shr ebx,16
- and bl,0fh
- or byte ptr [XMS_desc+6],bl
-
- ; Allocate memory Block
- mov cx,ax ; Olny allocate the Lockable memory
- shr eax,16
- mov bx,ax
- mov ax,0501h
- int 31h
- mov word ptr Call_data.c_edx,offset dpmi_aloc_err
- jc print_error
- ; Returns BX:CX with the linear address
- mov word ptr [XMS_Desc+2],cx ; Set Desciptor base
- mov byte ptr [XMS_Desc+4],bl
- mov byte ptr [XMS_desc+7],bh
- mov _tmpL_xms_base,CX ; store base address
- mov _tmpH_xms_base,BX
-
- No_DPMI_MEMORY:
-
- ; Set DPL for all descriptors to CPL
- mov si,offset GDT + 13
- setDPL:
- or byte ptr [si],01100000b
- add si,8
- cmp si, 12*8 +5
- jbe setDPL
-
- ; Allocate 12 descriptors
- mov AX,0000h
- mov CX,12
- int 31h
- mov word ptr Call_data.c_edx,offset erralc_mesg
- jc print_error
-
- mov DPMI_Selector,ax
-
-
- ;---- Set Descriptors -----
- xor esi,esi
- set_Descr:
- mov ax,000Ch ; Set Descriptor
- mov bx,DPMI_Selector
- push bx
- mov edi,offset GDT +8
- mov edx,esi
- shl edx,3
- add edi,edx
- int 31h
- mov word ptr Call_data.c_edx,offset errset_mesg
- jc print_error
-
- mov ax,0003h ; Get Next Selector incremental value
- int 31h
- add DPMI_Selector,ax
- inc esi
- cmp esi,12 ; must set 12 descriptors
- jb set_Descr
-
- pop DS ; Pop all the selector values that were pushed.
-
- ASSUME DS:DATA32
- MOV DATA_sel,DS
-
- POP CODE16_sel
- POP CODE32_sel
- POP PSP_sel
- POP DOS_DATA_sel
- POP DOS_CODE_sel
- POP TheStack_sel
- POP VIDEO_sel
- POP BASE_sel
- POP XMS_sel
- POP FLAT_CODE32_sel
- POP FLAT_DATA_sel
-
- mov es,[PSP_Sel] ; Restore environment pointer
- pop word ptr es:[02Ch]
-
-
-
-
- mov es,DOS_data_sel
- ASSUME ES:DOS_CODE
-
-
- mov eax,ES:xms_usage_tmp
- mov xms_usage,eax ; return store the acual amout allocted
-
- mov eax,dword ptr ES:_tmpL_xms_base
- mov xms_base,eax ; store the base address
-
-
- ; Get the base interrupt values of the PIC's
- mov ax,0400h
- int 31h
- mov ES:PIC1_base,dh
- mov ES:PIC2_base,dl
-
- mov ax,0205h
- mov cx,Code32_sel
-
- ; set int vector
- setdmpiInts macro in
- mov edx,offset irq&in
- int 31h
- inc bl
- endm
-
- mov bl,es:PIC1_base
- x=0
- rept 8
- setdmpiInts %x
- x=x+1
- endm
- mov bl,es:PIC2_base
- x=8
- rept 8
- setdmpiInts %x
- x=x+1
- endm
-
- mov edx,offset DPMI_EmulateRealInterupt
- mov bl,20h
- int 31h
-
- mov ss,[TheStack_sel]
- mov ss:[Real_ESP],0
- mov ss:[Real_SS],0
-
- mov esp,Normal_Stack
-
- mov es:DPMI_entry,offset start32
- mov ax,CODE32_sel
- mov es:DPMI_entry+2,ax
-
-
- ;----- Jump to 32bit mode through CODE 32 descriptor -----
- jmp dword ptr es:DPMI_entry
-
-
- ASSUME DS:DOS_CODE
-
- print_error:
- push Call_data.c_edx
- mov Call_data.c_edx,offset all_DPMI_err
- call print
- pop Call_data.c_edx
- call print
- dpmi_exit:
- mov ah,4ch
- int 21h
-
- print proc near
- mov Call_data.c_eax,0900h
- mov Call_data.c_DS,DOS_CODE
- mov ax,0300h ; sim real int
- mov bl,21h
- mov bh,0
- mov edi,offset call_data
- xor cx,cx
- int 31h
- ret
- endp
-
-
-
- No_DPMI:
- ;ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ
- ; Jups here if the operating system dos not support DPMI.
- ; Must enter protected mode directly.
- ;
- ;ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
-
- ; See if in V86 mode Because if so we can't go any further
- smsw ax ; Not allowed to use, MOV EAX,CR0
- test al,1
- jz in_Real_mode
- mov dx,offset _inV86_err
- jmp exit_InitError
-
- in_Real_mode:
- ; See if enough base memory
- cmp fs:Base_Segment,09A00h
- ja no_mem
-
- cmp xms_driver,00
- jz No_XMS_MEMORY
-
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
- ; Use the XMS services to allocate extended memoey
- cmp fs:xms_usage,0
- jz Extended_mem_set
-
- ; Must have XMS V3.0 to work
- mov ah,00 ; Get XMS Version number
- call XMS_Driver
- cmp ah,3
- jae xms_V3
- ; mov dx,offset xms_vers_err
- ; jmp exit_InitError
- xms_V3:
-
-
- ; QUERY FREE EXTENDED MEMORY
- MOV AH,08h
- call XMS_Driver ; returns eax with KB free
- and eax,0ffffh
- and al,0FCh ; want page granular
- shl eax,10 ; put KB -> bytes
-
- ;Only Allocate memory defined in xms_usage
- cmp eax,fs:xms_usage
- jbe LvXmsSize
- mov eax,fs:xms_usage
- LvXmsSize: mov fs:xms_usage,eax
-
- mov edx,eax
- shr edx,10
- and dl,0FCh ; want page granular
-
- call set_xms_limit ; set limit to eax
-
- ; ALLOCATE ANY EXTENDED MEMORY BLOCK ( size in eDX )
- mov ah,09h
- call XMS_Driver
- cmp ax,1
- jz xms_allod
- mov dx,offset xms_alloc_err
- jmp exit_InitError
- xms_allod:
- mov XMS_handle,dx
-
- ; LOCK THE ALLOCATED EXTENDED MEMORY BLOCK
- mov ah,0ch
- mov dx,XMS_handle
- call XMS_Driver
- cmp ax,1
- jz xms_locked
- mov dx,offset xms_lock_err
- jmp exit_InitError
- xms_locked: ; DX:BX has "PHYSICAL" address.
- mov word ptr [XMS_Desc+2],bx ;set xms descriptor
- mov byte ptr [XMS_Desc+4],dl ; Base.
- mov byte ptr [XMS_Desc+7],dh
- mov word ptr fs:xms_base,BX ; set base of block
- mov word ptr fs:xms_base+2,DX
-
- jmp Extended_mem_set
-
-
- No_XMS_MEMORY:
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
- ; ALLOCATE EVERY SINGLE BYTE OF EXTENDED MEMORY IF NO XMS DRIVER IS INSTALLED
-
- ; GET EXTENDED MEMORY SIZE FROM CMOS RAM -
- mov al,24 ; get MSB
- out 70h,al
- in al,71h
- shl ax,8
- mov al,23 ; get LSB
- out 70h,al
- in al,71h
-
- and eax,0ffffh
- shl eax,10
- mov fs:xms_usage,eax
- call set_xms_limit ; set limit to eax
- mov fs:xms_base,100000h ; start block at 1MB
- Extended_mem_set:
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
-
- ; Extended memory is allocated at this point
-
- CLI
- in al,21h
- mov oirqMask,al
- in al,0a1h
- mov oirqMask+1,al
-
- ;-- remap IRQ int vectors ---
- mov bl,Pic_Base
- mov bh,Pic_Base+8
- call set_8259intvec
-
- mov al,oirqMask
- out 21h,al
- mov al,oirqMask+1
- out 0A1h,al
-
- cli
-
- ; THE INTERRUPT DESCRIPTOR TABLE
-
- ; Use memory for the Interrupt Descriptor Table and the TSS
-
- mov ax,fs:Base_Segment ; Set IDT Reg base
- mov es,ax
- and eax,0ffffh
- shl eax,4
- mov dword ptr IDTR_value+2,eax
- mov fs:[IDT_base],eax
-
- xor eax,eax ; Clear all the new memory
- xor edi,edi
- mov ecx,(8*256 +TSS_Ends+16)/4
- cld
- rep stosd
-
-
- ;--- Build the Interrupt Descriptor Table ---
- mov eax,InterruptGATE_a
- mov edx,InterruptGATE_B
- xor cl,cl
- xor si,si
- @MakeIDT:
- mov es:[si],eax ; Put into memory
- mov es:[si+4],edx ; Put into memory
- add si,8
- dec cl
- jnz @MakeIDT
-
-
- ;---- Set interrupt vector 31h ------
- mov word ptr es:[31h*8],offset MyDPMI_services
-
- ;---- Set interrupt vector 21h ------
- mov word ptr es:[21h*8],offset Go_REAL_MODE
- mov word ptr es:[21h*8+2], Dos_Code_desc - GDT
-
- ; ---- Set hardware and exception interrupt handlers --------
- setexecp macro n
- mov word ptr es:[n*8],offset _386exception_&n
- mov word ptr es:[(Pic_Base+n)*8],offset firstIRQ&n
- endm
- x=0
- rept 16
- setexecp %x
- x=x+1
- endm
-
- ; ---- Set general protection exception handler interrupt --------
- mov word ptr es:[13*8],offset General_Exeption_Handler
-
- ; ---- Set real mode interrupt emulation handler interrupt --------
- mov word ptr es:[20h*8],offset My_EmulateRealInterupt
-
-
- ;-- Build the Task State Segment --
- add fs:Base_Segment,80h
- mov es,fs:Base_Segment
-
-
-
- xor eax,eax ; Get TSS base address
- mov ax,es
- shl eax,4
-
- mov fs:tss_Level0ESP,eax ; Store address level0 ESP of TSS
- add fs:tss_Level0ESP,offset tss_esp0
-
- mov MyMain_TSS_Desc+2,ax ; Load Base address of TSS descriptor
- shr eax,16
- mov byte ptr MyMain_TSS_Desc+4,al
-
-
-
- ; Load important TSS fields
- ; The level0 ESP field is set when real mode interrupt emulation is called
- mov es:tss_ss0, TheSTACK_Desc - GDT ; Priv. 0 SS
- mov es:tss_iobase, 068h
- mov es:tss_ioend,11111111b
-
- ; TSS is now built . Time to set the base descriptor base address just
- ; after the TSS and IDT.
-
- add fs:Base_Segment,(TSS_Ends+15)/16 ; inc Base_Segment
- call Allocate_Base
-
- CLI ; Can't have interrupts anymore
-
- ; Load the Interrupt descriptor table register
- lidt qword ptr IDTR_value
-
- ; Load the Global descriptor table register
- mov EAX,DOS_CODE
- shl EAX,4
- add dword ptr GDTR_value+2 , EAX
- lgdt qword ptr GDTR_value
-
- ; Enter Protected Mode
- mov eax,CR0
- or al,1 ; Set PE bit of CR0
- mov CR0,eax
-
- jmp FlushP ; Flush instruction prefetch counter
-
- FlushP:
-
-
- mov ax,MyMain_TSS_Desc - GDT ; Set TR to any valid TSS
- ltr ax
-
- mov ax,data_desc - GDT
- mov ds,ax
- assume ds:data32
-
- mov ss,ds:[TheStack_sel] ; Setup Protected mode stack
- mov esp,Normal_Stack
-
- mov SS:[Real_SS],V86_Stack ; Setup initial V86 stack
- mov SS:[Real_ESP ],V86_stack_size
-
- db 0EAh ; Jump to 32bit mode through CODE 32 descr
- dw offset Setup_Pmode , Code32_Desc - GDT
- ;--------------------------------------------------------------------------
- ; END OF PROTECTED MODE INITALIZATION
- ;--------------------------------------------------------------------------
-
- ;----------------------------------------------------------------------------
- ;ƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒ INTERNAL ROUTINES ƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒ
- ;----------------------------------------------------------------------------
- assume ds:dos_code
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
- set_xms_limit proc
- ; Set the xms descriptor limit.
- shr eax,12
- dec eax
- mov word ptr [XMS_Desc+0],ax ; set limit [0..15]
- shr eax,16
- or byte ptr [XMS_desc+6],al ; limit [16..19]
- ret
- endp
-
-
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
- Allocate_Base proc
- mov ax,fs:Base_Segment ; Set BASE data descriptor to this
- and eax,0ffffh
- shl eax,4
- mov word ptr [Base_Desc +2 ],ax
- shr eax,16
- mov byte ptr [Base_Desc +4 ],al
- ret
- ENDP
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
- exit_error: mov ah,9 ; print error message
- int 21h
- jmp Exit_To_MSDOS
-
- ;˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙˘˙
- Cant_Enter_dmpiPMode: mov dx,offset pmiERr
- jmp exit_error
-
- No_Mem: mov dx,offset No_Mem_err
- jmp exit_error
-
-
- align 16
- NON_DPMI_initalize_Size equ $ - NON_DPMI_initalize_start:
-
- dosstart endp
- DOS_CODE ENDS
-
- TheSTACK SEGMENT public stack 'stack' USE32
- db Normal_stack dup (?)
- TheSTACK ENDS
-
- V86_STACK SEGMENT public stack 'stack' USE16
- db V86_stack_size dup (?)
- V86_STACK ENDS
-
-
- END DosStart
-